﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using PdfSharp.Drawing;

namespace DeltaFlex.Eines
{
    public class PDFTextMultiColumn : IPDFElement
    {
        #region [ Propiedades ]

        private List<string> _text;
        private PDFTextStyle _textStyle;
        private double _numColumns;
        private double _colWidthReduction;
        private bool _fitToPageHeight;
        private double _height;
        private List<List<PDFText>> _columns;

        public List<string> Text
        {
            get { return this._text; }
            set { this._text = value; }
        }

        public PDFTextStyle TextStyle
        {
            get { return this._textStyle; }
            set { this._textStyle = value; }
        }

        public double NumColumns
        {
            get { return this._numColumns; }
            set { this._numColumns = value; }
        }

        public double ColWidthReduction
        {
            get { return this._colWidthReduction; }
            set { this._colWidthReduction = value; }
        }

        public bool FitToPageHeight
        {
            get { return this._fitToPageHeight; }
            set { this._fitToPageHeight = value; }
        }

        public double Height
        {
            get { return this._height; }
            set { this._height = value; }
        }

        #endregion

        #region [ Constructors ]

        public PDFTextMultiColumn()
            : this(new List<string>(), 1, new PDFTextStyle(), 0)
        { }

        public PDFTextMultiColumn(List<string> text, int numColumns, PDFTextStyle textStyle)
            : this(text, numColumns, textStyle, 0)
        { }

        public PDFTextMultiColumn(List<string> text, int numColumns, PDFTextStyle textStyle, double colWidthReduction)
        {
            this._text = text;
            this._numColumns = numColumns;
            this._colWidthReduction = colWidthReduction;
            this._textStyle = textStyle;
        }

        #endregion

        #region [ Override Functions ]

        internal override double Paint(XGraphics gfx, XRect rect)
        {
            if (this._columns.Count == 0 || this._columns[0].Count == 0)
                return 0.0;

            double nextPosY = rect.Y;
            double textHeight = this._columns[0][0].GetTotalHeight(gfx, rect.Width, null);
            int numRows = 0;
            this._columns.ForEach(c => numRows = Math.Max(numRows, c.Count));

            double colWidth = (rect.Width / this._numColumns);

            for (int r = 0; r < numRows; r++)
            {
                double nextPosX = rect.X;

                for(int c = 0; c < this._columns.Count; c++)
                {
                    if (this._columns[c].Count <= r)
                        break;

                    this._columns[c][r].Paint(gfx, new XRect(new XPoint(nextPosX, nextPosY), new XSize(colWidth - this._colWidthReduction, textHeight)));
                    nextPosX += colWidth;
                }
                nextPosY += textHeight;
            }

            return nextPosY;
        }

        internal override double GetTotalHeight(XGraphics gfx, double rectWidth, double? remainingHeight)
        {
            if (this._columns != null && this._columns.Count > 0)
            {
                return this._height;
            }

            int numCols = (int)this._numColumns;

            double colWidth = (rectWidth / this._numColumns);
            
            List<string> lines = new List<string>();

            double totalHeight = 0;
            foreach (var strng in this._text)
            {
                string strFinal = strng;
                if (String.IsNullOrEmpty(strFinal))
                    strFinal = " ";
                PDFText txt = new PDFText(strFinal, this._textStyle) { ColWidthReduction = this._colWidthReduction };
                List<string> linesAux = new List<string>();

                totalHeight += txt.GetTotalHeightAndLines(gfx, colWidth - this._colWidthReduction, remainingHeight, out linesAux);
                
                lines.AddRange(linesAux);
            }
            
            double lineHeight = totalHeight / lines.Count;

            int maxRowsPerCol = (lines.Count / numCols);
            if (FitToPageHeight || (maxRowsPerCol * lineHeight > remainingHeight))
            {
                maxRowsPerCol = Convert.ToInt32(remainingHeight / lineHeight);
            }

            this._columns = new List<List<PDFText>>();

            int currentIndex = 0;

            for (int c = 0; c < numCols; c++)
            {
                List<PDFText> newCol = new List<PDFText>();
                int colBreak = maxRowsPerCol;
                for (; currentIndex < lines.Count; currentIndex++)
                {
                    colBreak--;
                    newCol.Add(new PDFText(lines[currentIndex].Trim(), this._textStyle) { ForceJustified = this._textStyle.TextAlignement == TextAlign.Justify, ColWidthReduction = this._colWidthReduction });
                    if (colBreak == 0)
                    {
                        currentIndex++;
                        break;
                    }
                }

                this._columns.Add(newCol);
            }

            if (remainingHeight.HasValue)
            {
                if (remainingHeight.Value < totalHeight / this._numColumns)
                {
                    this._height = remainingHeight.Value;
                    return this._height;
                }
            }
            
            this._height = totalHeight / this._numColumns;
            
            return this._height;
        }

        #endregion
    }
}
